//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "common.h"
#include "iterator.h"
#include "array_base.h"

FC_NAMESPACE_BEGIN


template <class T, class Allocator>
class dynamic_array : public array_base<T, Allocator>
{
public:
	typedef T										value_type;
	typedef T*										pointer;
	typedef const T*								const_pointer;
	typedef T&										reference;
	typedef const T&								const_reference;
	typedef T*										iterator;
	typedef const T*								const_iterator;
	typedef fc::reverse_iterator<iterator>			reverse_iterator;
	typedef fc::reverse_iterator<const_iterator>	const_reverse_iterator;
	typedef size_t									size_type;
	typedef ptrdiff_t								difference_type;
	typedef dynamic_array<T, Allocator>				this_type;
	typedef array_base<T, Allocator>				base_type;
	typedef typename base_type::allocator_type		allocator_type;

	using base_type::get_allocator;
	using base_type::set_allocator;
	using base_type::fill;
	using base_type::resize;
	using base_type::swap;

	using base_type::m_data;
	using base_type::m_size;

	dynamic_array()
		: base_type()
		{
		}

	explicit dynamic_array( const allocator_type& alloc )
		: base_type(alloc)
		{
		}

	explicit dynamic_array( size_t n, const T& value = T(), const allocator_type& alloc = allocator_type() )
		: base_type(alloc)
		{
			resize( n, value );
		}

	dynamic_array( const this_type& x )
		: base_type()
		{
			*this = x;
		}

	bool empty() const		{ return m_size == 0; }
	size_t size() const		{ return m_size; }
	T* data()				{ return m_data; }
	const T* data() const	{ return m_data; }

	reference front()					{ return m_data[0]; }
	const_reference front() const		{ return m_data[0]; }
	reference back()					{ return m_data[m_size - 1]; }
	const_reference back() const		{ return m_data[m_size - 1]; }
	iterator begin()					{ return m_data; }
	const_iterator begin() const		{ return m_data; }
	iterator end()						{ return m_data + m_size; }
	const_iterator end() const			{ return m_data + m_size; }
	const_iterator	cbegin() const		{ return m_data; }
	const_iterator	cend() const		{ return m_data + m_size; }
	reverse_iterator rend()				{ return reverse_iterator(begin()); }
	const_reverse_iterator rend() const	{ return const_reverse_iterator(begin()); }
	reverse_iterator rbegin()			{ return reverse_iterator(end()); }
	const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }

	reference operator []( size_t i ) { return m_data[i]; }
	const_reference operator []( size_t i ) const { return m_data[i]; }

	reference at( size_t i )
	{
		FC_ASSERT(i < size());
		return m_data[i];
	}

	const_reference at( size_t i ) const
	{
		FC_ASSERT(i < size());
		return m_data[i];
	}

	bool iterator_is_valid( const_iterator it ) const
	{
		return (it >= begin() && it <= end());
	}

};


template <class T, class Allocator> inline
	void swap( dynamic_array<T, Allocator>& a, dynamic_array<T, Allocator>& b )
	{
		a.swap(b);
	}

template <class T> inline
	bool operator ==( const dynamic_array<T>& a, const dynamic_array<T>& b )
	{
		return( &a == &b || (a.size() == b.size() && fc::equal(a.begin(), a.end(), b.begin())) );
	}

template <class T> inline
	bool operator !=( const dynamic_array<T>& a, const dynamic_array<T>& b )
	{
		return !(a == b);
	}


FC_NAMESPACE_END
